package com.bomberdroid.ui;

import java.util.Timer;
import java.util.TimerTask;

import com.bomberdroid.model.Bombe;
import com.bomberdroid.model.Bonus;
import com.bomberdroid.model.Objet;
import com.bomberdroid.model.Player;
import com.bomberdroid.protocols.ConnectedThread;
import com.bomberdroid.protocols.Connexion;
import com.bomberdroid.protocols.DataSharing;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Toast;

public class ClientGame extends Activity {
	
	private Connexion connexion;
	private ConnectedThread server;
	private int mapId;
	private ArrayAdapter<String> playersList;
	
	// Handler to manage communications from server
	private Handler.Callback c = new Handler.Callback() {
		public boolean handleMessage(Message msg) {
			return handleCommunication(msg);
		}
	};
	private Handler handler = new Handler(c);
	
	// Timer for sending data throught socket
	private Timer timer = new Timer();
	private int tickCount = 0;
	private TimerTask task = new TimerTask() {
		@Override public void run() {
			if(!end){
				checkEndGame();
				send();
			}
			else if(tickCount >= endTick){
				finish();
			}
			tickCount++;
		}
	};
	
	private GamePanel gamePanel;
	private Player[] players;
	private static int nbDead = 0;
	
	private boolean end = false;
	private int endTick = 0;
	private String endMessage = "";
	
	@Override protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		DataSharing.message = "";
		nbDead = 0;
		Objet.endGame = false;
		
		this.mapId = DataSharing.Client_map;
		this.playersList = DataSharing.Client_playersList;
		this.connexion = DataSharing.Client_connexion;
		this.server = DataSharing.Client_server;
		
		this.server.setHandler(this.handler);
		
		this.gamePanel = new GamePanel(this, this.mapId, false);
		this.setContentView(this.gamePanel);
		
		this.initGame();

		this.timer.schedule(task, 0, 50);
	}
	
	/**	Will init the game with the clients data */
	private void initGame(){
		this.players = new Player[this.playersList.getCount()];
		for(int i=0; i < this.playersList.getCount() ; i++){
			this.players[i] = this.gamePanel.getMap().getListeJ()[i];
			this.players[i].setNom(this.playersList.getItem(i));
			this.players[i].setIndice(i);
			if(this.players[i].getNom().equals(this.connexion.getIdentity())){
				this.gamePanel.setInd(i);
			}
		}
		this.gamePanel.getMap().setListeJ(this.players);
	}
	
	public static void incNbDead(){
		nbDead++;
	}
	
	private void checkEndGame(){
		if(nbDead >= this.players.length -1 ){
			this.gamePanel.getControls().setEndGame(true);
			Objet.endGame = true;
			this.end = true;
			this.endTick = tickCount+60;
			Player winner = null;
			for(Player p : this.players){
				if(!p.isMort())
					winner = p;
			}
			this.endMessage = (winner != null ? "Winner :\n"+winner.getNom() : "Game is draw !");
			this.runOnUiThread(new Runnable() {public void run() {
				Toast.makeText(getBaseContext(), endMessage, Toast.LENGTH_LONG).show();
			}});
		}
	}
	
	/** Handles messages from clients comming through ConnectedThread and the Handler
	 * @param msg
	 * @return
	 */
	private boolean handleCommunication(Message msg){
		boolean res = true;
		String s = new String((byte[])msg.obj, 0, msg.arg1);
		Log.d("Communication", "ClientGame received : "+s);
		String[] messages = s.split("&");
		for(String mess : messages){
			String[] data = mess.split(";");
			if(data[0].equals("0")){
				Toast.makeText(this.getApplicationContext(), "Host server disconnected.", Toast.LENGTH_LONG).show();
				this.end = true;
				this.finish();
			}
			else if(data[0].equals("1")){
				if(Integer.parseInt(data[1]) != this.gamePanel.getInd())
					this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1])).updateState(Integer.parseInt(data[2]));
			}
			else if(data[0].equals("2")){
				Player p = this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1]));
				p.setX(Integer.parseInt(data[2]));
				p.setY(Integer.parseInt(data[3]));
			}
			else if(data[0].equals("3")){
				int X = Integer.parseInt(data[2]);
				int Y = Integer.parseInt(data[3]);
				Player p = this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1]));
				Objet[][] grille = this.gamePanel.getMap().getGrille();
				
				grille[Y][X] = new Bombe(X, Y, p, grille);
			}
			else if(data[0].equals("4")){
				Bombe b = (Bombe)this.gamePanel.getMap().getGrille()[Integer.parseInt(data[2])][Integer.parseInt(data[1])];
				b.explose();
			}
			else if(data[0].equals("5")){
				Objet[][] grille = this.gamePanel.getMap().getGrille();
				grille[Integer.parseInt(data[3])][Integer.parseInt(data[2])]
						= new Bonus(Integer.parseInt(data[2]), Integer.parseInt(data[3]), grille, Integer.parseInt(data[1]));
			}
			else if(data[0].equals("6")){
				Bonus b = (Bonus)this.gamePanel.getMap().getGrille()[Integer.parseInt(data[3])][Integer.parseInt(data[2])];
				b.take(this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1])));
			}
			else if(data[0].equals("7")){
				this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1])).setMort(true);
			}
			else if(data[0].equals("8")){
				if(Integer.parseInt(data[1]) != this.gamePanel.getInd())
					this.playersList.remove(data[1]);
			}
			else{
				res = false;
			}
		}		
		return res;
	}
	
	private void send(){
		String mess = DataSharing.message;
		if(!mess.equals("")){
			DataSharing.message = "";
			try{this.server.write(mess);}catch(Exception e){this.finish();}
		}
	}
	
	@Override protected void onDestroy() {
		Log.d("Communication", "ClientGame : Destroying");
		this.gamePanel.surfaceDestroyed(this.gamePanel.getHolder());
		this.gamePanel = null;
		if(!this.task.cancel())
			Log.d("Communication", "ClientGame : Enable to stop task");
		this.task = null;
		this.timer.cancel();
		this.timer = null;
		// If the stopping was not because of the server
		if(!this.end){
			// Notify the server about leaving
			try {this.server.write("0;"+this.connexion.getIdentity());} catch (Exception e) {e.printStackTrace();}
		}
		DataSharing.message = "";
		super.onDestroy();
	}
	
}
